package com.yang.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yang.domain.User;
import com.yang.dto.Authorization;
import com.yang.dto.UserDto;
import com.yang.exception.BaseException;
import com.yang.mapper.UserMapper;
import com.yang.service.UserService;
import com.yang.utils.JwtUtil;
import com.yang.utils.ThreadLocalUtil;
import com.yang.vo.ResponseResult;
import com.yang.vo.UserVo;
import org.apache.commons.codec.cli.Digest;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.tomcat.util.security.MD5Encoder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import sun.security.provider.MD5;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public ResponseResult register(Authorization authorization) {
        //校验用户名长度
        if (authorization.getUsername().length()<5
                ||authorization.getUsername().length()>12){
            throw new BaseException("用户名必须5~12位之间");
        }

        //校验密码长度
        if (authorization.getPassword().length()<4
                ||authorization.getPassword().length()>12){
            throw new BaseException("密码长度必须在4~12位之间");
        }

        //判断账号是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,authorization.getUsername());
        if (userMapper.selectOne(queryWrapper)!=null){
            return ResponseResult.fail("该账号已存在");
        }


        //添加到数据库
        userMapper.insert(
                User.builder()
                        .username(authorization.getUsername())
                        //对密码进行MD5加密
                        .password(DigestUtils.md5Hex(authorization.getPassword()))
                        .build());

        return ResponseResult.success("注册成功");
    }

    @Override
    public ResponseResult login(Authorization authorization) {
        //1.构建查询条件
        LambdaQueryWrapper<User>queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,authorization.getUsername())
                .eq(User::getPassword,DigestUtils.md5Hex(authorization.getPassword()));

        //2.查询该用户
        User user = userMapper.selectOne(queryWrapper);
        if (Objects.isNull(user)){
            throw new BaseException("用户名或密码错误");
        }

        // 3.判断用户是否处于登录状态，若处于登录状态，则不能重复登陆 (从redis中获取令牌信息)
        String value = (String) redisTemplate.opsForValue().get("userId:"+user.getId().toString());
        if (!Objects.isNull(value)){
            throw new BaseException("账号不能重复登陆");
        }

        //4.生成jwt令牌
        Map<String,Object>map=new HashMap<>();
        map.put("id",user.getId().toString());
        String jwt = JwtUtil.createJWT(map);

        // 5.将用户id作为key,jwt令牌作为value 存入redis,并设置有效期为1天
        redisTemplate.opsForValue().set("userId:"+user.getId().toString(),jwt,JwtUtil.ttlMillis, TimeUnit.MILLISECONDS);

        return ResponseResult.success("登陆成功",jwt);
    }

    @Override
    public ResponseResult updatePassword(Authorization authorization) {

        //1.从ThreadLocal中获取用户信息
        Long userId= Long.valueOf(ThreadLocalUtil.get().toString());

        //2.根据id查询用户信息
        User user = userMapper.selectById(userId);

        //3.将旧密码进行比对，若一样，则允许修改；否则，不允许修改密码
        if (!DigestUtils.md5Hex(authorization.getOldPassword())
                                    .equals(user.getPassword())){
            throw new BaseException("旧密码错误，修改失败");
        }

        //4.修改密码
        user.setPassword(DigestUtils.md5Hex(authorization.getPassword()));
        userMapper.updateById(user);

//        // 5.将redis中缓存的旧密码生成的令牌剔除，设为过期
//        redisTemplate.expire("userId:"+userId.toString(),0,TimeUnit.MILLISECONDS);

        //退出登录
        logout();

        return ResponseResult.success("密码修改成功,请重新登陆",null);
    }

    @Override
    public ResponseResult setOrUpdateSecurity(Authorization authorization) {

        //1.从ThreadLocal中获取用户id
        Long userId= Long.valueOf(ThreadLocalUtil.get().toString());

        //2.根据id查询出用户信息
        User user = userMapper.selectById(userId);

        //3.修改密保信息
        user.setSecurityQuestion(authorization.getSecurityQuestion());
        user.setSecurityAnswer(authorization.getSecurityAnswer());
        userMapper.updateById(user);

        return ResponseResult.success("密保修改成功",null);
    }

    @Override
    public ResponseResult getSecurity() {

        // 获取密保问题
        //1.获取用户id
        Long userId = Long.valueOf(ThreadLocalUtil.get().toString());

        //2.根据用户id获取密保信息
        User user = userMapper.selectById(userId);
        Authorization securityInfo = Authorization.builder()
                .securityQuestion(user.getSecurityQuestion())
                .build();
        return ResponseResult.success(securityInfo);
    }

    @Override
    public ResponseResult getUserInfo() {
        //1.获取用户id
        Long userId = Long.valueOf(ThreadLocalUtil.get().toString());

        //2.根据用户id获取用户信息
        User user = userMapper.selectById(userId);

        //3.拷贝要返回的属性
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);

        return ResponseResult.success(userVo);
    }

    @Override
    public ResponseResult updateUserInfo(UserDto userDto) {

        //  更新用户信息
        //1.获取用户id
        Long userId = Long.valueOf(ThreadLocalUtil.get().toString());

        //2.获取用户信息
        User user = userMapper.selectById(userId);

        //3.修改个人信息
        if (!StringUtils.isEmpty(userDto.getAvatar())){
            user.setAvatar(userDto.getAvatar());
        }

        if (!StringUtils.isEmpty(userDto.getEmail())){
            user.setEmail(userDto.getEmail());
        }

        if (!StringUtils.isEmpty(userDto.getNickname())){
            user.setNickname(userDto.getNickname());
        }

        userMapper.updateById(user);

        return ResponseResult.success("修改成功",null);
    }

    @Override
    public ResponseResult logout() {

        //1.获取用户id
        String userId = ThreadLocalUtil.get().toString();

        //2.清除redis中存的令牌
        redisTemplate.expire("userId:"+userId,0,TimeUnit.MILLISECONDS);

        return ResponseResult.success("退出成功");
    }
}
